home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 406_01 / atoc / function.c < prev    next >
Text File  |  1993-11-09  |  7KB  |  286 lines

  1. /*=========================================================================
  2.  
  3.     ATOC function declarations module
  4.  
  5. =========================================================================*/
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "atoc.h"
  10.  
  11. /**/    /* this version requires that function and all args are on one line */
  12.  
  13. /* #define TESTING */ 
  14.  
  15. #define MAXARGS        32    /* max args one function can have */
  16.  
  17.  
  18. /*-------------------------------------------------------------------------
  19. local global variables
  20. -------------------------------------------------------------------------*/
  21. PRIVATE char *args[ MAXARGS ] = {    /* individual arguments */
  22.     NULL
  23. };
  24. PRIVATE char temp[ MAXLINELENGTH ];    /* temp buffer */
  25.  
  26.  
  27. /*-------------------------------------------------------------------------
  28. function( s ) looks for function declarations or prototypes and expands or
  29. removes their arguments.
  30. -------------------------------------------------------------------------*/
  31. function( s )
  32. char *s;
  33. {
  34.     char *start, *stop, *strchr(), *strrchr();
  35.     char *cp, *dp, *malloc();
  36.     char *argname();
  37.     int ansi_style, i;
  38.  
  39.     if ( isfunction( s ) )
  40.     {
  41.         start = strchr( s, '(' ) + 1;
  42.         stop = strrchr( s, ')' );
  43.         if ( strchr( s, ';' ) == NULL )        /* declaration */
  44.         {
  45.             /* make list of arguments in *args[] */
  46.             i = 0;
  47.             for ( cp = start; cp < stop; ++cp )
  48.             {
  49.                 while ( cp < stop && isspace( *cp ) )
  50.                     ++cp;
  51.                 if ( cp < stop )
  52.                 {
  53.                     dp = temp;
  54.                     while ( cp < stop && *cp != ',' )
  55.                         *dp++ = *cp++;
  56.                     *dp = '\0';
  57.                     /* strip trailing spaces */
  58.                     for ( --dp; dp >= temp && isspace( *dp ); --dp )
  59.                         *dp = '\0';
  60.                     if ( ( args[ i ] = malloc( strlen( temp ) + 1 ) ) != NULL )
  61.                     {
  62.                         strcpy( args[ i ], temp );
  63.                         ++i;
  64.                     }
  65.                 }
  66.             }
  67.             args[ i ] = NULL;
  68.  
  69.             /* see if ANSI or K&R style */
  70.             /* ANSI will have white space within arg */
  71.             ansi_style = FALSE;
  72.             for ( cp = args[ 0 ]; *cp; ++cp )
  73.                 if ( isspace( *cp ) )
  74.                 {
  75.                     ansi_style = TRUE;
  76.                     break;
  77.                 }
  78.  
  79.             if ( ansi_style )
  80.             {
  81.                 /* save any trailing stuff */
  82.                 strcpy( temp, stop + 1 );
  83.                 /* remove end of current line */
  84.                 *start = '\0';
  85.                 /* rebuild line with arg names */
  86.                 strcat( buffer, " " );
  87.                 for ( i = 0; args[ i ]; ++i )
  88.                 {
  89.                     if ( i > 0 )
  90.                         strcat( buffer, ", " );
  91.                     strcat( buffer, argname( args[ i ] ) );
  92.                 }
  93.                 strcat( buffer, " )" );
  94.                 strcat( buffer, temp );
  95.                 /* flag that there are args to output */
  96.                 decflag = TRUE;
  97.             }
  98.         }
  99.         else                    /* prototype */
  100.         {
  101.             if ( stop > start )
  102.                 strcpy( start, stop );
  103.         }
  104.     }
  105. }
  106. /*-------------------------------------------------------------------------
  107. argname( s ) finds the argument name in s and puts it in a local buffer,
  108. returning a pointer to it.
  109. -------------------------------------------------------------------------*/
  110. PRIVATE char *argname( s )
  111. char *s;
  112. {
  113.     static char name[ 80 ];
  114.     char *cp, *np, *strchr(), *strtok();
  115.  
  116.     strcpy( name, s );        /* get temp copy */
  117.     if ( ( cp = strchr( name, '[' ) ) != NULL ) /* remove any [] */
  118.         *cp = '\0';
  119.     for ( cp = name; *cp; ++cp )    /* remove all non-id chars */
  120.         if ( ! isid( *cp ) )
  121.             *cp = ' ';
  122.     np = NULL;            /* find last valid name */
  123.     for ( cp = name; ( cp = strtok( cp, " " ) ) != NULL; cp = NULL )
  124.         np = cp;
  125.     return( np );            /* return it */
  126. }
  127. /*-------------------------------------------------------------------------
  128. declarations( fo ) outputs all the declaration lines we saved from the
  129. function declaration. Called from outside this module.
  130. -------------------------------------------------------------------------*/
  131. declarations( fo )
  132. FILE *fo;
  133. {
  134.     int i;
  135.  
  136.     for ( i = 0; args[ i ]; ++i )
  137.         fprintf( fo, "%s;\n", args[ i ] );
  138.     args[ 0 ] = NULL;
  139. }
  140. /*-------------------------------------------------------------------------
  141. isfunction( s ) returns TRUE if it thinks this line is a function declaration
  142. or prototype, or FALSE otherwise.
  143. -------------------------------------------------------------------------*/
  144. PRIVATE int isfunction( s )
  145. char *s;
  146. {
  147.     char *cp, *strchr(), *strstr();
  148.     int pnflag, pnlevel;
  149.     int firstid, secondid, whitespace;
  150.  
  151.     /* should have at least one pair of parens with proper nesting */
  152.     /* at least two identifiers prior to the opening paren */
  153.     /* only certain non-identifier characters allowed */
  154.     /* and nothing beyond final nesting paren except semicolon or comments */
  155.     pnflag = FALSE;
  156.     pnlevel = 0;
  157.     firstid = secondid = whitespace = FALSE;
  158.     for ( cp = s; *cp; ++cp )
  159.         if ( ! isid( *cp ) )
  160.         {
  161.             if ( *cp == '(' )
  162.             {
  163.                 pnflag = TRUE;
  164.                 ++pnlevel;
  165.             }
  166.             else if ( *cp == ')' )
  167.             {
  168.                 if ( pnflag && pnlevel > 0 )
  169.                 {
  170.                     --pnlevel;
  171.                     if ( pnlevel == 0 )
  172.                     {
  173.                         /* check thru stuff after last nesting paren */
  174.                         for ( ++cp; *cp; ++cp )
  175.                             switch( *cp )
  176.                             {
  177.                                 case '\t':
  178.                                 case ' ':
  179.                                 case ';':
  180.                                     break;
  181.                                 case '/':
  182.                                     if ( *( cp + 1 ) == '*' )
  183.                                         for ( cp += 2; *cp; ++cp )
  184.                                             if ( *cp == '*' && *( cp + 1 ) == '/' )
  185.                                             {
  186.                                                 ++cp;
  187.                                                 break;
  188.                                             }
  189.                                     break;
  190.                                 default:
  191. #ifdef TESTING
  192.                                     printf( "*** NOT A FUNCTION BECAUSE OF <%c> AFTER LAST PAREN ***\n", *cp );
  193. #endif
  194.                                     return( FALSE );
  195.                             }
  196.                         break; /* stuff after parens is all ok */
  197.                     }
  198.                 }
  199.                 else
  200.                 {
  201. #ifdef TESTING
  202.                     printf( "*** NOT A FUNCTION BECAUSE PAREN NESTING IS BAD ***\n" );
  203. #endif
  204.                     return( FALSE );
  205.                 }
  206.             }
  207.             else if ( isspace( *cp ) )
  208.             {
  209.                 if ( ! pnflag )
  210.                     if ( firstid && ! secondid )
  211.                         whitespace = TRUE;
  212.             }
  213.             else if ( strchr( "*,;[]", *cp ) == NULL )
  214.             {
  215. #ifdef TESTING
  216.                 printf( "*** NOT A FUNCTION BECAUSE OF <%c> ***\n", *cp );
  217. #endif
  218.                 return( FALSE );
  219.             }
  220.         }
  221.         else
  222.         {
  223.             if ( ! pnflag )
  224.                 if ( ! firstid )
  225.                     firstid = TRUE;
  226.                 else if ( whitespace )
  227.                     secondid = TRUE;
  228.         }
  229.  
  230.     /* no parens at all? */
  231.     if ( ! pnflag )
  232.     {
  233. #ifdef TESTING
  234.         printf( "*** NOT A FUNCTION BECAUSE THERE ARE NO PARENS ***\n" );
  235. #endif
  236.         return( FALSE );
  237.     }
  238.  
  239.     /* abnormal nesting result? */
  240.     if ( pnlevel != 0 )
  241.     {
  242. #ifdef TESTING
  243.         printf( "*** NOT A FUNCTION BECAUSE PAREN NESTING IS BAD ***\n" );
  244. #endif
  245.         return( FALSE );
  246.     }
  247.  
  248.     /* bad id/whitespace sequence? */
  249.     if ( ! firstid || ! whitespace || ! secondid )
  250.     {
  251. #ifdef TESTING
  252.         printf( "*** NOT A FUNCTION BECAUSE ID/WHITESPACE/PAREN SEQUENCE IS WRONG ***\n" );
  253. #endif
  254.         return( FALSE );
  255.     }
  256.  
  257.     /* 'else' keyword? */
  258.     if ( ( cp = strstr( s, "else" ) ) != NULL )
  259.         if ( cp == s || ! isid( *( cp - 1 ) ) )
  260.             if ( ! isid( *( cp + 4 ) ) )
  261.             {
  262. #ifdef TESTING
  263.                 printf( "*** NOT A FUNCTION BECAUSE OF 'ELSE' KEYWORD ***\n" );
  264. #endif
  265.                 return( FALSE );
  266.             }
  267.  
  268.     /* 'return' keyword? */
  269.     if ( ( cp = strstr( s, "return" ) ) != NULL )
  270.         if ( cp == s || ! isid( *( cp - 1 ) ) )
  271.             if ( ! isid( *( cp + 6 ) ) )
  272.             {
  273. #ifdef TESTING
  274.                 printf( "*** NOT A FUNCTION BECAUSE OF 'RETURN' KEYWORD ***\n" );
  275. #endif
  276.                 return( FALSE );
  277.             }
  278.  
  279.  
  280. #ifdef TESTING
  281.     printf( "FUNCTION->>> " );
  282. #endif
  283.     return( TRUE );
  284. }
  285. /*=======================================================================*/
  286.